/**
 * 集群类
 *
 * Created by snowingsea on 2020/01/19.
 */

const cluster = require('cluster');
const debug = require('debug')('phoenix:cluster');
const workerKind = {
  requestHandler: 'WORKER_REQUEST_HANDLER',
  consumer: 'WORKER_MESSAGE_CONSUMER',
};
const clusterConfig = {
  [workerKind.requestHandler]: 4,
  [workerKind.consumer]: 2,
  // WORKER_WATCH_DOG_HELPER: 1,
};

/**
 * 自定义cluster类
 */
class Cluster {
  constructor() {
    this.wokers = new Map();
  }

  /**
   * 添加worker
   */
  addWorker(role, index) {
    const worker = cluster.fork();
    this.wokers.set(worker.process.pid, { worker, role, index });
    debug('CLUSTER: %s %d forked', role, index);
    worker.send({ config: global.config, role, index });
    return worker;
  }

  /**
   * 移除worker
   * @param pid 进程id
   */
  removeWorker(pid) {
    this.wokers.delete(pid);
  }

  /**
   * 启动cluster
   */
  start() {
    Object.keys(clusterConfig).forEach((role) => {
      for (let i = 0; i < (Math.min(require('os').cpus().length, clusterConfig[role])); i += 1) {
        this.addWorker(role, i);
      }
    });

    // when a worker dies (exits), create a worker to replace it
    cluster.on('exit', (worker, code, signal) => {
      debug('CLUSTER: Worker %d died with exit code %d (%s)', worker.id, code, signal);
      const { role, index } = this.wokers.get(worker.process.pid);
      this.removeWorker(worker.process.pid);
      this.addWorker(role, index);
    });
  }
}

/**
 * Export model definition object.
 */
module.exports = {
  Cluster,
  workerKind,
  clusterConfig,
};
